Tasks
1. Dating Trends Over Time
- Visualize how the mode of meeting for the first time has changed
over the years. Create two (2) charts in this section to highlight some
important pattern(s).
Wrangling and Cleaning
# grouping meeting places into 6 categories [type_met]
df <- df %>%
mutate(type_met = case_when(
meeting_type %in% c("Internet", "Internet Dating or Phone App", "Internet Social Network", "Online Gaming", "Internet Chat", "Internet Site", "Met Online") ~ "Online",
meeting_type %in% c("Primary or Secondary School", "College") ~ "School/College",
meeting_type %in% c("Business Trip", "Work Neighbors", "Customer-Client Relationship") ~ "Work-Related Activity",
meeting_type %in% c("Bar or Restaurant", "Private Party", "Church", "Volunteer Organization") ~ "Social Settings",
meeting_type %in% c("Blind Date", "Military", "One-time Service Interaction", "On Vacation", "Public Place") ~ "Special Circumstance/Other",
TRUE ~ "Other"
))
# filter to only rows with years reported (no NA's or 'Refused')
df_filtered <- filter(df, !is.na(year_met) & year_met != "Refused")
# Preparing for chart 2 data
df_filtered$years_met_num <- as.numeric(as.character(df_filtered$year_met))
# Group years into 10-year intervals starting from 1930
df_filtered <- df_filtered %>%
mutate(year_group = cut(years_met_num,
breaks = seq(1930, 2040, by = 10), # Define decade intervals
labels = c("1930-1939", "1940-1949", "1950-1959",
"1960-1969", "1970-1979", "1980-1989",
"1990-1999", "2000-2009", "2010-2019",
"2020-2029", "2030-2039"),
right = FALSE)) # Left-inclusive intervals
Custom Palette
palette <- c("#7D7C84", "#af5265", "#f9b97f", "#d3d3d3", "#567b81")
palette2 <- c("#19377c","#8b4183", "#ce5c73", "#ed9062", "#eacd6c")
Base graph
# Base graph: Mode of meeting [All respondents][no time][overall]
base_graph <- ggplot(df, aes(x = fct_rev(fct_infreq(type_met)),
fill= type_met, # different color by meeting type
stat = "identity"))+
geom_bar(width = 0.6)+
coord_flip()+ #turns the boxplot on its side
scale_fill_manual(values = palette)+ #palette
labs(x=NULL, y= "Counts", title = "How did you meet your partner?", fill = "Meeting Type")+
theme_minimal()
base_graph + theme(legend.position = "none")

Chart 1: stacked bar (counts)
# Chart 1: Meeting mode, frequency over time [filters NAs & 'Refused']
# Ensure year_met is numeric
df_filtered <- df_filtered %>%
mutate(year_met = as.numeric(as.character(year_met))) # Convert factor to numeric
# Stacked bar plot, over time [year_met: ungrouped]
graph_1 <- ggplot(df_filtered, aes(x = year_met, fill = type_met))+
geom_bar(width = .75)+
scale_x_continuous(breaks = seq(1940, 2020, by = 10))+
scale_fill_manual(values = palette)+
labs(x = NULL, y = "Counts", fill = "Meeting Type",
title = "How people met their partners over time (frequency)")+
coord_fixed(ratio = 0.2) + # Adjust aspect ratio (smaller values stretch horizontally)+
theme_minimal()+
theme(axis.text.x = element_text(angle = 75, hjust = 0.8, size = 7))
graph_1

Graph 2: stacked bar (proportions)(grouped)
# Graph 2: Meeting mode, percentage over time [filters NAs][Stacked Bar Chart]
# Filled bar plot, over time
graph_2 <- ggplot(df_filtered, aes(x=year_group, fill=type_met))+
geom_bar(position = "fill", width = 0.6)+
scale_fill_manual(values = palette)+
labs(x = "Decade", y = "Percent(%)", fill = "Meeting Type",
title = "How people met their partners over time (%)")+
theme_minimal()+
theme(axis.text.x = element_text(angle = 70, hjust = 1, vjust = 1.15, size=7))
graph_2

- Create an alternative visualization of the same data. Discuss which
visualization you recommend to the editor and why. Rely on at least
three specific data visualization principles or theories discussed in
class to justify your choice.
Chart 3: Line Graph (Alternative)
#frequency (counts) of meeting type over time
# dataframe: count meeting types by year
line <- df_filtered %>%
group_by(year_met, type_met) %>% # Group by year and meeting type
dplyr::summarise(count = n(), .groups = "drop") # Count occurrences, using dplyr package
# Basic line graph
graph_3 <- ggplot(line, aes(x = year_met, y = count, color = type_met, group = type_met)) +
scale_color_manual(values = palette)+
geom_line(alpha=0.85, linewidth = 0.75)+
scale_x_continuous(breaks = seq(1940, 2020, by = 10))+
geom_point(alpha=0.75, size=1)+
coord_fixed(ratio = 0.5) +
labs(
title = "Meeting Type Populatity Over Time",
x = "Year",
y = "Count",
color = "Meeting Type"
)+
theme_minimal()+
theme(axis.text.x = element_text(angle = 90, hjust = 1, size = 7)) # Add lines for each meeting type
graph_3

My recommendation: Chart 1 is nice for visualizing
changes in the the frequency of modes every year, while drawing
attention to the rise of some modes (i.e., internet). However, chart 1
might not be the best means of comparing proportional distribution. To
combat this, chart 2 was created to explore the share (%), with years
grouped into decades. While chart 2 does a better job than chart 1 at
highlighting which modes are more popular than others over time,
aggregating by decade results in measurement error which can mislead
viewers – a lot of changes can happen in 10 years. The last
vizualization, chart 3, circumvents these issues. Not only does a
frequency-based line graph allow viewers to clearly decipher which modes
are above and below others in terms of popularity, but it also allows us
to compare across all years. I would recommend chart 3.
2. Age is Just a Number
- Create one (1) visualization to show the relationship between a
respondent’s age and their partner’s age, accounting for the gender of
the respondent? Identify the main pattern in the graph via an annotation
directly added to the plot.
Chart 4: Scatterplot
# respondent_age: The age of the respondent = resp_age
# partner_age: The age of their partner = part_age
# gender: The gender of the respondent = resp_gender
# Scatter plot with regression lines
graph_4 <- ggplot(data = df, aes(x = resp_age, y = part_age, color = resp_gender)) +
geom_point(alpha = 0.5, size=1)+ # Scatter points with some transparency
geom_smooth(method = "lm", se = TRUE)+ # Adding regression lines
scale_color_manual(values = c("#567b81", "#af5265", "#7D7C84"))+
labs(title = "Relationship Between Respondent's Age and Partner's Age",
x = "Respondent's Age",
y = "Partner's Age",
color = "Gender"
)+
annotate("text", x = 100, y = 12, label = "Ages couples are positively correlated,
with slight differences by gender",
color = "#7D7C84", size = 3.5, fontface= "bold.italic", hjust = 1, linewidth=1)+
theme_minimal()
Warning: Ignoring unknown parameters: `linewidth`
graph_4

- Use Edward Tufte’s principles to critique the plot above. Which of
the changes would improve the plot in your opinion?
Answer: If I were Tufte, I would say that the color,
the grid lines, and the relatively large data points are unnecessary.
Based on data-inc-ration alone, the graph is not at par with what Tuft
would have visioned for a effective and compelling vizual aid. I think
that the scatter plot would improve (from Tufte standards) from smaller
lm lines, and smaller data points. Additionally, I would unbold the
annotation/caption.
3. Politics and Dating
- Explore how the political affiliation of partners affects how
couples meet and stay together. Create two (2) charts in this section.
Make sure to use some variation in the type of visualizations. Discuss
which visualization you recommend to your editor and why.
Cleaning & Wrangling
# ensure factor levels align
df$resp_party <- factor(df$resp_party, levels = union(levels(df$resp_party), levels(df$part_party)))
df$part_party <- factor(df$part_party, levels = union(levels(df$resp_party), levels(df$part_party)))
# Creates 2 new categorical variables: summarizes respondents' and partners' political affiliations into three possibilities (dem, ind, rep)
library(dplyr)
df <- df %>%
mutate(resp_party_type = case_when(
resp_party %in% c("Strong Democrat", "Not Strong Democrat", "Leans Democrat") ~ "Dem",
resp_party %in% c("Undecided/Independent/Other") ~ "Ind",
resp_party %in% c("Strong Republican", "Not Strong Republican", "Leans Republican") ~ "Rep" # Assign NA for any unexpected values
))
df <- df %>%
mutate(part_party_type = case_when(
part_party %in% c("Strong Democrat", "Not Strong Democrat", "Leans Democrat") ~ "Dem",
part_party %in% c("Undecided/Independent/Other") ~ "Ind",
part_party %in% c("Strong Republican", "Not Strong Republican", "Leans Republican") ~ "Rep"
))
# Create the alignment variable: party_pair
df <- df %>%
mutate(party_pair = paste(resp_party_type, part_party_type, sep = "-"))
# filtering NA pairs
party_pair_filtered <- df %>%
filter(party_pair != "Dem-NA" & party_pair != "Ind-NA" & party_pair != "Rep-NA")
Graph 5: Stacked Barplot (counts)
#graph 5: Stacked bar chart for meeting types by partner alignment
graph_5 <- ggplot(party_pair_filtered, aes(x = party_pair, fill = type_met)) +
geom_bar(position = "Stack") + # Normalize to proportions
coord_flip()+
scale_fill_manual(values = palette)+
labs(
title = "Most Popular Meeting Types by Party Alignment",
x = "Political Alignment",
y = "Counts",
fill = "Meeting Type"
) +
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, hjust = 1))
graph_5

# New DF: Count occurrences of meeting types for each alignment
party_pair_df <- df %>%
group_by(party_pair, type_met) %>%
dplyr::summarise(count = n(), .groups = "drop")
Chart 6: Boxplot
# Chart 6: boxplot showing party alignment on duration of relationships
graph_6 <- ggplot(party_pair_filtered, aes(x = party_pair, y = duration, fill = party_pair)) +
geom_boxplot() +
coord_flip()+
scale_fill_manual(values = c("#567b81", "#567b81", "#567b81", "#d3d3d3", "#d3d3d3", "#d3d3d3", "#af5265", "#af5265", "#af5265"))+
labs(
title = "Relationship Duration by Political Alignment",
x = NULL,
y = "Duration of Relationship (Years)",
fill = NULL
)+
theme_minimal()+ theme(legend.position="none")
graph_6

Discussion:
- Write a short narrative (~150 words) based on your visualization,
integrating data insights with a compelling story. This narrative should
be suitable for a feature article, highlighting key findings and their
implications.
Narrative: The way couples meet and the longevity of
their relationships seem closely tied to political alignment. Social
settings dominate as the most popular meeting type for politically
aligned couples, such as “Dem-Dem” and “Rep-Rep,” while
mixed-affiliation couples like “Dem-Ind” show a more diverse
distribution of meeting types, including online platforms and
work-related activities. This suggests that shared political beliefs may
streamline social circles, making it easier for like-minded individuals
to connect.
When it comes to relationship duration, couples with the same
political affiliation, particularly “Dem-Dem” and “Rep-Rep,” tend to
have longer-lasting relationships compared to mixed-affiliation pairs.
This pattern hints at the stabilizing influence of shared values and
worldviews on partnerships. These findings highlight how political
identity extends beyond ideology, influencing both how couples form and
how they endure over time.
4. Your Turn to Choose
There are lots of other variables that could make for an interesting
story, for example, educational background differences, relationship
stages (First Met, Romantic, Live together & Married), regional
patterns, relationship break ups, sexual behavior etc. Select some
variables of your choice to tell a story that captures an interesting
insight into the data.
Create one (1) chart in this section to highlight some important
patterns. Briefly discuss which visualization you recommend to your
editor, why you think the visualization is useful, and which patterns it
serves to highlight.
# probability of marriage across meeting types
df_status_mar <- df %>%
filter(ship_status== "married")
# Summarize counts of meeting types for married respondents
pie_mar_df <- df_status %>%
group_by(type_met) %>%
dplyr::summarise(count = n(), .groups = "drop")
# Pie chart: marriage across meeting types
graph7.1 <- ggplot(pie_ship_df, aes(x = "", y = count, fill = type_met)) +
geom_bar(stat = "identity", width = 1, color = "white")+ # Create bars
scale_fill_manual(values = palette)+
coord_polar("y", start = 0)+ # Transform to pie chart
#theme_void() + # Remove axes and grids
labs(title = "Comparing Meeting Types Between Married and Divorced/Separated Respondents",
y = "Married", x="percent",
)+
theme_minimal()+
theme(legend.position="none")+
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank())
# probability of divorce, separation, breakup across meeting types
df_status_div_sep <- df %>%
filter(ended_mar== "divorce" | ended_mar == "separation with no divorce" | ended_nonmar == "We broke up")
# Summarize counts of meeting types for married respondents
pie_nonmar_df <- df_status_div_sep %>%
group_by(type_met) %>%
dplyr::summarise(count = n(), .groups = "drop")
# Pie chart: divorce/separation across meeting types
graph7.2 <-ggplot(pie_nonmar_df, aes(x = "", y = count, fill = type_met)) +
geom_bar(stat = "identity", width = 1, color = "white")+
scale_fill_manual(values = palette)+
coord_polar("y", start = 0) + # Transform to pie chart
#theme_void() + # Remove axes and grids
labs(
fill = NULL, x="percent",
y="Divorced/Separated"
)+
theme_minimal()+
theme(
axis.text.x = element_blank(), # Remove x-axis text
axis.ticks.x = element_blank(), # Remove x-axis ticks
plot.title = element_text(hjust = 0.5, size = 14), # Center and adjust title size
legend.position = "none"
)
graph_7_comb <- graph7.1 + graph7.2
graph_7 <- graph_7_comb + theme(legend.position="right")
graph_7

Discussion: The dual pie chart effectively compares
how meeting types differ between married and divorced/separated
respondents. It highlights that social settings are prominent for both
groups, while work-related activities are more common among married
couples. The use of percentages within each slice (observing the two
interactive plots) would make the comparison even clearer, allowing
readers to easily grasp the relative importance of each meeting
type.
Interactivity
5. Make Two Plots Interactive
- Choose 2 of the plots you created above and add interactivity. For
at least one of these interactive plots, this should not be done through
the use of
ggplotly
Interactive Plot 1: plotly piechart version
library(plotly)
# Create interactive pie chart
interactive_pie_mar <- plot_ly(
data = pie_mar_df,
labels = ~type_met, # Meeting types as labels
values = ~count, # Counts as values
type = 'pie', # Specify pie chart
textinfo = 'label+percent', # Show labels and percentages
hoverinfo = 'label+value+percent', # Hover info: label, value, percentage
marker = list(colors = palette) # Custom colors
) %>%
layout(
title = "Distribution of Meeting Types Among Married Respondents",
legend = list(orientation = "h") # Horizontal legend
)
interactive_pie_mar
# Create interactive pie chart
interactive_pie_divsep <- plot_ly(
data = pie_nonmar_df,
labels = ~type_met, # Meeting types as labels
values = ~count, # Counts as values
type = 'pie', # Specify pie chart
textinfo = 'label+percent', # Show labels and percentages
hoverinfo = 'label+value+percent', # Hover info: label, value, percentage
marker = list(colors = palette) # Custom colors
) %>%
layout(
title = "Distribution of Meeting Types Among Married Respondents",
legend = list(orientation = "h") # Horizontal legend
)
interactive_pie_divsep
# Interactive Plot 2:
ggplotly(graph_3)
NA
Interactive Plot 2:
- Briefly describe to the editor why interactivity in these
visualizations is particularly helpful for a reader, referencing user
engagement theories or interaction design principles.
Describe: Interactivity in these visualizations
allows readers to explore the data in a more engaging and intuitive way.
For example, hovering over the pie chart slices reveals exact
percentages and meeting types, making it easier to compare how married
and divorced/separated couples met. Similarly, the line graph enables
readers to focus on specific trends, such as the sharp rise of online
meeting platforms after 2000. These features make the data more
accessible and encourage readers to uncover insights on their own.
6. Data Table
To allow the reader to explore the survey data by themselves a bit,
select a few useful variables, rename them appropriately for the table
to be self-explanatory, and add an interactive data table to the output.
Make sure the columns are clearly labeled. Select the appropriate
options for the data table (e.g. search bar, sorting, column filters,
in-line visualizations etc. – as far as the tools supplied in lecture
allow).
# Interactive table:
library(DT)
# Select and rename relevant columns
interactive_tab <- df %>%
select(
type_met,
ship_status,
duration,
resp_gender,
resp_party,
part_party
) %>%
rename(
`Meeting Type` = type_met,
`Relationship Status` = ship_status,
`Length of Relationship (Years)` = duration,
`Respondent's Gender` = resp_gender,
`Respondent's Political Affiliation` = resp_party,
`Partner's Political Affiliation` = part_party
)
# Create the interactive data table
datatable(
interactive_tab,
class = "cell-border stripe hover compact", # Styling options
filter = "top", # Add column filters at the top
options = list(
pageLength = 10, # Number of rows per page
autoWidth = TRUE, # Automatically adjust column widths
dom = 'Bfrtip', # Add buttons for export/download
buttons = c('copy', 'csv', 'excel') # Export options
),
caption = "Explore Meeting Types and Relationship Details of Survey Respondents"
)
Technical Details
The data comes in a reasonably clean file. However, if you do find
issues with the data, recode any values, etc. please make this clear in
the code (and if significant add into the description).
If needed for your visualization, you can add visual drapery like
icons, images etc. but you are certainly not obligated to do that. What
is important, however, to use a consistent style across all your
visualizations.
Part of the task will be transforming the dataset into a shape that
allows you to plot what you want. For some plots, you will necessarily
need to be selective in what to include and what to leave out.
Make sure to use at least three different types of graphs,
e.g. line graphs, scatter, histograms, bar charts, dot plots, heat maps,
etc.
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAxIC0gRGF0aW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKZGF0ZTogMjAyNS0wMi0xMgphdXRob3I6IFRob21hcyBCcmFtYm9yCi0tLQoKIVtdKGltYWdlcy9jbGlwYm9hcmQtMjM0ODQ3NDExOC5wbmcpCgojIyBTY2VuYXJpbwoKSW1hZ2luZSB5b3UgYXJlIGEgZGF0YSBzY2llbnRpc3QgYXQgYSByZXNwZWN0ZWQgbWVkaWEgb3V0bGV0IC0tIHNheSB0aGUgIk5ldyBZb3JrIFRpbWVzIi4gWW91ciBlZGl0b3Igd2FudHMgdG8gc3VwcG9ydCB0aGUgd3JpdGluZyBvZiBhIGZlYXR1cmUgYXJ0aWNsZSBhYm91dCAqSG93IENvdXBsZXMgTWVldCBhbmQgU3RheSBUb2dldGhlciouIFlvdXIgZWRpdG9yLWluLWNoaWVmIGFza3MgeW91IHRvIGFuYWx5emUgc29tZSBkYXRhIGZyb20gYW4gW2V4dGVuc2l2ZSBzdXJ2ZXkgY29uZHVjdGVkIGJ5IGEgcmVzZWFyY2hlciBhdCBTdGFuZm9yZCBVbml2ZXJzaXR5XShodHRwczovL2RhdGEuc3RhbmZvcmQuZWR1L2hjbXN0KS4KClNpbmNlIHRoZXJlIGlzICoqbm8gd2F5IHRoYXQgYWxsIGZlYXR1cmVzIG9mIHRoZSBkYXRhIGNhbiBiZSByZXByZXNlbnRlZCoqIGluIHN1Y2ggYSBtZW1vLCBmZWVsIGZyZWUgdG8gcGljayBhbmQgY2hvb3NlIHNvbWUgcGF0dGVybnMgdGhhdCB3b3VsZCBtYWtlIGZvciBhIGdvb2Qgc3RvcnkgLS0gb3V0bGluaW5nIGltcG9ydGFudCBwYXR0ZXJucyBhbmQgcHJlc2VudGluZyB0aGVtIGluIGEgdmlzdWFsbHkgcGxlYXNpbmcgd2F5LgoKVGhlIGZ1bGwgYmFja2dyb3VuZCBhbmQgdGV4dCBvZiB0aGUgc3Rvcnkgd2lsbCBiZSByZXNlYXJjaGVkIGJ5IGEgd3JpdGVyIG9mIHRoZSBtYWdhemluZSAtLSB5b3VyIGlucHV0IHNob3VsZCBiZSBiYXNlZCBvbiB0aGUgZGF0YSBhbmQgc29tZSBjb21tb24gc2Vuc2UgKGkuZS4gbm8gbmVlZCB0byByZWFkIHVwIG9uIHRoaXMpLiBJdCBkb2VzIGhlbHAsIGhvd2V2ZXIsIHRvIGJyaWVmbHkgZGVzY3JpYmUgd2hhdCB5b3UgYXJlIHByZXNlbnRpbmcgYW5kIHdoYXQgaXQgaGlnaGxpZ2h0cy4KClByb3ZpZGUgKipwb2xpc2hlZCBwbG90cyoqIHRoYXQgYXJlIHJlZmluZWQgZW5vdWdoIHRvIGluY2x1ZGUgaW4gdGhlIG1hZ2F6aW5lIHdpdGggdmVyeSBsaXR0bGUgZnVydGhlciBtYW5pcHVsYXRpb24gKGFscmVhZHkgaW5jbHVkZSB2YXJpYWJsZSBkZXNjcmlwdGlvbnMgW2lmIG5lY2Vzc2FyeSBmb3IgdW5kZXJzdGFuZGluZ10sIHRpdGxlcywgc291cmNlIFtlLmcuICJIb3cgQ291cGxlcyBNZWV0IGFuZCBTdGF5IFRvZ2V0aGVyIChSb3NlbmZlbGQsIFJldWJlbiwgRmFsY29uIDIwMTgpIl0sIGFwcHJvcHJpYXRlIGNvbG9ycywgZm9udHMgZXRjLikgYW5kIGFyZSB1bmRlcnN0YW5kYWJsZSB0byB0aGUgYXZlcmFnZSByZWFkZXIgb2YgdGhlICJOZXcgWW9yayBUaW1lcyIuIFRoZSBkZXNpZ24gZG9lcyBub3QgbmVlZCB0byBiZSBOWVRpbWVzLWxpa2UuIEp1c3QgYmUgY29uc2lzdGVudC4KCiMjIERhdGEKCldlIHdpbGwgYmUgdXNpbmcgdGhlIDIwMTcgd2F2ZSBvZiB0aGUgSENNU1Qgc3VydmV5IC0gcHJvdmlkZWQgYXMgYEhDTVNUX2NvdXBsZXMucmRzYC4gVGhlIGZpbGUgYEhDTVNUX3ZhcmlhYmxlX2Rlc2NyaXB0aW9ucy5wZGZgIGNvbnRhaW5zIG1vc3Qgb2YgdGhlIHZhcmlhYmxlIGRlc2NyaXB0aW9ucyBhbmQgY29kaW5nIG9mIHJlc3BvbnNlcy4KCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KERUKQoKCnNldHdkKCJ+L0Rlc2t0b3AvU3ByaW5nIDIwMjUvRGF0YSBWaXovUiBEaXJlY3RvcnkgLSBEYXRhX1Zpei8wM19kYXRpbmdfR1JBREVEIikKZmlsZW5hbWUgPC0gZmlsZS5jaG9vc2UoKQpjb3VwbGVzIDwtIHJlYWRSRFMoZmlsZW5hbWUpCgojIGV4dHJhY3RpbmcgdmFycyBhbmQgY3JlYXRpbmcgZGYKZGYgPC0gZGF0YS5mcmFtZShJRCA9IGNvdXBsZXMkQ2FzZUlELCAKICAgICAgICAgICAgICAgICBjb3VwbGVzJERPVl9CcmFuY2gsIAogICAgICAgICAgICAgICAgIHNoaXBfc3RhdHVzID0gY291cGxlcyRwYXJ0bmVyc2hpcF9zdGF0dXMsIAogICAgICAgICAgICAgICAgIG1lZXRpbmdfdHlwZSA9IGNvdXBsZXMkbWVldGluZ190eXBlLCAKICAgICAgICAgICAgICAgICB5ZWFyX21ldCA9IGNvdXBsZXMkUTIxQV9ZZWFyLCAKICAgICAgICAgICAgICAgICBtb250aF9tZXQgPSBjb3VwbGVzJFEyMUFfTW9udGgsCiAgICAgICAgICAgICAgICAgeWVhcl9iZWdpbiA9IGNvdXBsZXMkUTIxQl9ZZWFyLAogICAgICAgICAgICAgICAgIHllYXJfbGl2X3RvZyA9IGNvdXBsZXMkUTIxQ19ZZWFyLAogICAgICAgICAgICAgICAgIHllYXJfbWFyID0gY291cGxlcyRRMjFEX1llYXIsCiAgICAgICAgICAgICAgICAgcmVzcF9hZ2UgPSBjb3VwbGVzJHBwYWdlLAogICAgICAgICAgICAgICAgIHBhcnRfYWdlID0gY291cGxlcyRROSwKICAgICAgICAgICAgICAgICByZXNwX2dlbmRlciA9IGNvdXBsZXMkcHBnZW5kZXIsCiAgICAgICAgICAgICAgICAgZHVyYXRpb24gPSBjb3VwbGVzJHJlbGF0ZV9kdXJhdGlvbl9hdF93Nl95ZWFycywKICAgICAgICAgICAgICAgICBzaGlwX3N0YXR1cyA9IGNvdXBsZXMkcGFydG5lcnNoaXBfc3RhdHVzLCAKICAgICAgICAgICAgICAgICByZXNwX3BhcnR5ID0gY291cGxlcyRwYXJ0eWlkNywKICAgICAgICAgICAgICAgICBwYXJ0X3BhcnR5ID0gY291cGxlcyR3Nl9xMTIsCiAgICAgICAgICAgICAgICAgZW5kZWRfbm9ubWFyID0gY291cGxlcyR3Nl9yZWxhdGlvbnNoaXBfZW5kX25vbm1hciwgCiAgICAgICAgICAgICAgICAgZW5kZWRfbWFyID0gY291cGxlcyR3Nl9yZWxhdGlvbnNoaXBfZW5kX21hcgogICAgICAgICAgICAgICAgICkKYGBgCgojIyBUYXNrcwoKIyMjIDEuIERhdGluZyBUcmVuZHMgT3ZlciBUaW1lCgphKSAgVmlzdWFsaXplIGhvdyB0aGUgbW9kZSBvZiBtZWV0aW5nIGZvciB0aGUgZmlyc3QgdGltZSBoYXMgY2hhbmdlZCBvdmVyIHRoZSB5ZWFycy4gQ3JlYXRlIHR3byAoMikgY2hhcnRzIGluIHRoaXMgc2VjdGlvbiB0byBoaWdobGlnaHQgc29tZSBpbXBvcnRhbnQgcGF0dGVybihzKS4KCioqV3JhbmdsaW5nIGFuZCBDbGVhbmluZyoqCgpgYGB7cn0KIyBncm91cGluZyBtZWV0aW5nIHBsYWNlcyBpbnRvIDYgY2F0ZWdvcmllcyBbdHlwZV9tZXRdCmRmIDwtIGRmICU+JQogIG11dGF0ZSh0eXBlX21ldCA9IGNhc2Vfd2hlbigKICAgIG1lZXRpbmdfdHlwZSAlaW4lIGMoIkludGVybmV0IiwgIkludGVybmV0IERhdGluZyBvciBQaG9uZSBBcHAiLCAiSW50ZXJuZXQgU29jaWFsIE5ldHdvcmsiLCAiT25saW5lIEdhbWluZyIsICJJbnRlcm5ldCBDaGF0IiwgIkludGVybmV0IFNpdGUiLCAiTWV0IE9ubGluZSIpIH4gIk9ubGluZSIsCiAgICBtZWV0aW5nX3R5cGUgJWluJSBjKCJQcmltYXJ5IG9yIFNlY29uZGFyeSBTY2hvb2wiLCAiQ29sbGVnZSIpIH4gIlNjaG9vbC9Db2xsZWdlIiwKICAgIG1lZXRpbmdfdHlwZSAlaW4lIGMoIkJ1c2luZXNzIFRyaXAiLCAiV29yayBOZWlnaGJvcnMiLCAiQ3VzdG9tZXItQ2xpZW50IFJlbGF0aW9uc2hpcCIpIH4gIldvcmstUmVsYXRlZCBBY3Rpdml0eSIsCiAgICBtZWV0aW5nX3R5cGUgJWluJSBjKCJCYXIgb3IgUmVzdGF1cmFudCIsICJQcml2YXRlIFBhcnR5IiwgIkNodXJjaCIsICJWb2x1bnRlZXIgT3JnYW5pemF0aW9uIikgfiAiU29jaWFsIFNldHRpbmdzIiwKICAgIG1lZXRpbmdfdHlwZSAlaW4lIGMoIkJsaW5kIERhdGUiLCAiTWlsaXRhcnkiLCAiT25lLXRpbWUgU2VydmljZSBJbnRlcmFjdGlvbiIsICJPbiBWYWNhdGlvbiIsICJQdWJsaWMgUGxhY2UiKSB+ICJTcGVjaWFsIENpcmN1bXN0YW5jZS9PdGhlciIsCiAgICBUUlVFIH4gIk90aGVyIgogICkpCgojIGZpbHRlciB0byBvbmx5IHJvd3Mgd2l0aCB5ZWFycyByZXBvcnRlZCAobm8gTkEncyBvciAnUmVmdXNlZCcpIApkZl9maWx0ZXJlZCA8LSBmaWx0ZXIoZGYsICFpcy5uYSh5ZWFyX21ldCkgJiB5ZWFyX21ldCAhPSAiUmVmdXNlZCIpCgojIFByZXBhcmluZyBmb3IgY2hhcnQgMiBkYXRhIApkZl9maWx0ZXJlZCR5ZWFyc19tZXRfbnVtIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGRmX2ZpbHRlcmVkJHllYXJfbWV0KSkKCiMgR3JvdXAgeWVhcnMgaW50byAxMC15ZWFyIGludGVydmFscyBzdGFydGluZyBmcm9tIDE5MzAKZGZfZmlsdGVyZWQgPC0gZGZfZmlsdGVyZWQgJT4lCiAgbXV0YXRlKHllYXJfZ3JvdXAgPSBjdXQoeWVhcnNfbWV0X251bSwKICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMTkzMCwgMjA0MCwgYnkgPSAxMCksICMgRGVmaW5lIGRlY2FkZSBpbnRlcnZhbHMKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCIxOTMwLTE5MzkiLCAiMTk0MC0xOTQ5IiwgIjE5NTAtMTk1OSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjE5NjAtMTk2OSIsICIxOTcwLTE5NzkiLCAiMTk4MC0xOTg5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMTk5MC0xOTk5IiwgIjIwMDAtMjAwOSIsICIyMDEwLTIwMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMjAtMjAyOSIsICIyMDMwLTIwMzkiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IEZBTFNFKSkgIyBMZWZ0LWluY2x1c2l2ZSBpbnRlcnZhbHMKCmBgYAoKKipDdXN0b20gUGFsZXR0ZSoqCgpgYGB7cn0KcGFsZXR0ZSA8LSBjKCIjN0Q3Qzg0IiwgIiNhZjUyNjUiLCAiI2Y5Yjk3ZiIsICIjZDNkM2QzIiwgIiM1NjdiODEiKQpgYGAKCioqQmFzZSBncmFwaCoqCgpgYGB7cn0KIyBCYXNlIGdyYXBoOiBNb2RlIG9mIG1lZXRpbmcgW0FsbCByZXNwb25kZW50c11bbm8gdGltZV1bb3ZlcmFsbF0KYmFzZV9ncmFwaCA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gZmN0X3JldihmY3RfaW5mcmVxKHR5cGVfbWV0KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD0gdHlwZV9tZXQsICMgZGlmZmVyZW50IGNvbG9yIGJ5IG1lZXRpbmcgdHlwZSAKICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IikpKyAKICBnZW9tX2Jhcih3aWR0aCA9IDAuNikrCiAgY29vcmRfZmxpcCgpKyAjdHVybnMgdGhlIGJveHBsb3Qgb24gaXRzIHNpZGUKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlKSsgI3BhbGV0dGUKICBsYWJzKHg9TlVMTCwgeT0gIkNvdW50cyIsIHRpdGxlID0gIkhvdyBkaWQgeW91IG1lZXQgeW91ciBwYXJ0bmVyPyIsIGZpbGwgPSAiTWVldGluZyBUeXBlIikrCiAgdGhlbWVfbWluaW1hbCgpCgpiYXNlX2dyYXBoICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKYGBgCgoqKkNoYXJ0IDE6IHN0YWNrZWQgYmFyIChjb3VudHMpKioKCmBgYHtyfQojIENoYXJ0IDE6IE1lZXRpbmcgbW9kZSwgZnJlcXVlbmN5IG92ZXIgdGltZSBbZmlsdGVycyBOQXMgJiAnUmVmdXNlZCddCgojIEVuc3VyZSB5ZWFyX21ldCBpcyBudW1lcmljCmRmX2ZpbHRlcmVkIDwtIGRmX2ZpbHRlcmVkICU+JQogIG11dGF0ZSh5ZWFyX21ldCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHllYXJfbWV0KSkpICAjIENvbnZlcnQgZmFjdG9yIHRvIG51bWVyaWMKCiMgU3RhY2tlZCBiYXIgcGxvdCwgb3ZlciB0aW1lIFt5ZWFyX21ldDogdW5ncm91cGVkXQpncmFwaF8xIDwtIGdncGxvdChkZl9maWx0ZXJlZCwgYWVzKHggPSB5ZWFyX21ldCwgZmlsbCA9IHR5cGVfbWV0KSkrCiAgZ2VvbV9iYXIod2lkdGggPSAuNzUpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTk0MCwgMjAyMCwgYnkgPSAxMCkpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiQ291bnRzIiwgZmlsbCA9ICJNZWV0aW5nIFR5cGUiLAogICAgICAgdGl0bGUgPSAiSG93IHBlb3BsZSBtZXQgdGhlaXIgcGFydG5lcnMgb3ZlciB0aW1lIChmcmVxdWVuY3kpIikrCiAgY29vcmRfZml4ZWQocmF0aW8gPSAwLjIpICsgICMgQWRqdXN0IGFzcGVjdCByYXRpbyAoc21hbGxlciB2YWx1ZXMgc3RyZXRjaCBob3Jpem9udGFsbHkpKwogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDc1LCBoanVzdCA9IDAuOCwgc2l6ZSA9IDcpKQogIApncmFwaF8xCgpgYGAKCioqR3JhcGggMjogc3RhY2tlZCBiYXIgKHByb3BvcnRpb25zKShncm91cGVkKSoqCgpgYGB7cn0KIyBHcmFwaCAyOiBNZWV0aW5nIG1vZGUsIHBlcmNlbnRhZ2Ugb3ZlciB0aW1lIFtmaWx0ZXJzIE5Bc11bU3RhY2tlZCBCYXIgQ2hhcnRdCgojIEZpbGxlZCBiYXIgcGxvdCwgb3ZlciB0aW1lIApncmFwaF8yIDwtIGdncGxvdChkZl9maWx0ZXJlZCwgYWVzKHg9eWVhcl9ncm91cCwgZmlsbD10eXBlX21ldCkpKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCB3aWR0aCA9IDAuNikrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkrCiAgbGFicyh4ID0gIkRlY2FkZSIsIHkgPSAiUGVyY2VudCglKSIsIGZpbGwgPSAiTWVldGluZyBUeXBlIiwKICAgICAgIHRpdGxlID0gIkhvdyBwZW9wbGUgbWV0IHRoZWlyIHBhcnRuZXJzIG92ZXIgdGltZSAoJSkiKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA3MCwgaGp1c3QgPSAxLCB2anVzdCA9IDEuMTUsIHNpemU9NykpCgpncmFwaF8yCmBgYAoKYikgIENyZWF0ZSBhbiBhbHRlcm5hdGl2ZSB2aXN1YWxpemF0aW9uIG9mIHRoZSBzYW1lIGRhdGEuIERpc2N1c3Mgd2hpY2ggdmlzdWFsaXphdGlvbiB5b3UgcmVjb21tZW5kIHRvIHRoZSBlZGl0b3IgYW5kIHdoeS4gUmVseSBvbiBhdCBsZWFzdCB0aHJlZSBzcGVjaWZpYyBkYXRhIHZpc3VhbGl6YXRpb24gcHJpbmNpcGxlcyBvciB0aGVvcmllcyBkaXNjdXNzZWQgaW4gY2xhc3MgdG8ganVzdGlmeSB5b3VyIGNob2ljZS4KCioqQ2hhcnQgMzogTGluZSBHcmFwaCAoQWx0ZXJuYXRpdmUpKioKCmBgYHtyfQojZnJlcXVlbmN5IChjb3VudHMpIG9mIG1lZXRpbmcgdHlwZSBvdmVyIHRpbWUKCiMgZGF0YWZyYW1lOiBjb3VudCBtZWV0aW5nIHR5cGVzIGJ5IHllYXIKbGluZSA8LSBkZl9maWx0ZXJlZCAlPiUKICBncm91cF9ieSh5ZWFyX21ldCwgdHlwZV9tZXQpICU+JSAgIyBHcm91cCBieSB5ZWFyIGFuZCBtZWV0aW5nIHR5cGUKICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSAgIyBDb3VudCBvY2N1cnJlbmNlcywgdXNpbmcgZHBseXIgcGFja2FnZSAKCiMgQmFzaWMgbGluZSBncmFwaApncmFwaF8zIDwtIGdncGxvdChsaW5lLCBhZXMoeCA9IHllYXJfbWV0LCB5ID0gY291bnQsIGNvbG9yID0gdHlwZV9tZXQsIGdyb3VwID0gdHlwZV9tZXQpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKwogIGdlb21fbGluZShhbHBoYT0wLjg1LCBsaW5ld2lkdGggPSAwLjc1KSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDE5NDAsIDIwMjAsIGJ5ID0gMTApKSsKICBnZW9tX3BvaW50KGFscGhhPTAuNzUsIHNpemU9MSkrCiAgY29vcmRfZml4ZWQocmF0aW8gPSAwLjUpICsgCiAgbGFicygKICAgIHRpdGxlID0gIk1lZXRpbmcgVHlwZSBQb3B1bGF0aXR5IE92ZXIgVGltZSIsCiAgICB4ID0gIlllYXIiLAogICAgeSA9ICJDb3VudCIsCiAgICBjb2xvciA9ICJNZWV0aW5nIFR5cGUiCiAgKSsgCiAgdGhlbWVfbWluaW1hbCgpKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDc1LCBoanVzdCA9IDEsIHNpemUgPSA3KSkgIyBBZGQgbGluZXMgZm9yIGVhY2ggbWVldGluZyB0eXBlCgpncmFwaF8zCmBgYAoKKipNeSByZWNvbW1lbmRhdGlvbioqOiBDaGFydCAxIGlzIG5pY2UgZm9yIHZpc3VhbGl6aW5nIGNoYW5nZXMgaW4gdGhlIHRoZSBmcmVxdWVuY3kgb2YgbW9kZXMgZXZlcnkgeWVhciwgd2hpbGUgZHJhd2luZyBhdHRlbnRpb24gdG8gdGhlIHJpc2Ugb2Ygc29tZSBtb2RlcyAoaS5lLiwgaW50ZXJuZXQpLiBIb3dldmVyLCBjaGFydCAxIG1pZ2h0IG5vdCBiZSB0aGUgYmVzdCBtZWFucyBvZiBjb21wYXJpbmcgcHJvcG9ydGlvbmFsIGRpc3RyaWJ1dGlvbi4gVG8gY29tYmF0IHRoaXMsIGNoYXJ0IDIgd2FzIGNyZWF0ZWQgdG8gZXhwbG9yZSB0aGUgc2hhcmUgKCUpLCB3aXRoIHllYXJzIGdyb3VwZWQgaW50byBkZWNhZGVzLiBXaGlsZSBjaGFydCAyIGRvZXMgYSBiZXR0ZXIgam9iIHRoYW4gY2hhcnQgMSBhdCBoaWdobGlnaHRpbmcgd2hpY2ggbW9kZXMgYXJlIG1vcmUgcG9wdWxhciB0aGFuIG90aGVycyBvdmVyIHRpbWUsIGFnZ3JlZ2F0aW5nIGJ5IGRlY2FkZSByZXN1bHRzIGluIG1lYXN1cmVtZW50IGVycm9yIHdoaWNoIGNhbiBtaXNsZWFkIHZpZXdlcnMgLS0gYSBsb3Qgb2YgY2hhbmdlcyBjYW4gaGFwcGVuIGluIDEwIHllYXJzLiBUaGUgbGFzdCB2aXp1YWxpemF0aW9uLCBjaGFydCAzLCBjaXJjdW12ZW50cyB0aGVzZSBpc3N1ZXMuIE5vdCBvbmx5IGRvZXMgYSBmcmVxdWVuY3ktYmFzZWQgbGluZSBncmFwaCBhbGxvdyB2aWV3ZXJzIHRvIGNsZWFybHkgZGVjaXBoZXIgd2hpY2ggbW9kZXMgYXJlIGFib3ZlIGFuZCBiZWxvdyBvdGhlcnMgaW4gdGVybXMgb2YgcG9wdWxhcml0eSwgYnV0IGl0IGFsc28gYWxsb3dzIHVzIHRvIGNvbXBhcmUgYWNyb3NzIGFsbCB5ZWFycy4gSSB3b3VsZCByZWNvbW1lbmQgY2hhcnQgMy4KCiMjIyAyLiBBZ2UgaXMgSnVzdCBhIE51bWJlcgoKYSkgIENyZWF0ZSBvbmUgKDEpIHZpc3VhbGl6YXRpb24gdG8gc2hvdyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSByZXNwb25kZW50J3MgYWdlIGFuZCB0aGVpciBwYXJ0bmVyJ3MgYWdlLCBhY2NvdW50aW5nIGZvciB0aGUgZ2VuZGVyIG9mIHRoZSByZXNwb25kZW50PyBJZGVudGlmeSB0aGUgbWFpbiBwYXR0ZXJuIGluIHRoZSBncmFwaCB2aWEgYW4gYW5ub3RhdGlvbiBkaXJlY3RseSBhZGRlZCB0byB0aGUgcGxvdC4KCioqQ2hhcnQgNDogU2NhdHRlcnBsb3QqKgoKYGBge3J9CiMgcmVzcG9uZGVudF9hZ2U6IFRoZSBhZ2Ugb2YgdGhlIHJlc3BvbmRlbnQgPSByZXNwX2FnZQojIHBhcnRuZXJfYWdlOiBUaGUgYWdlIG9mIHRoZWlyIHBhcnRuZXIgPSBwYXJ0X2FnZQojIGdlbmRlcjogVGhlIGdlbmRlciBvZiB0aGUgcmVzcG9uZGVudCA9IHJlc3BfZ2VuZGVyCgojIFNjYXR0ZXIgcGxvdCB3aXRoIHJlZ3Jlc3Npb24gbGluZXMKZ3JhcGhfNCA8LSBnZ3Bsb3QoZGF0YSA9IGRmLCBhZXMoeCA9IHJlc3BfYWdlLCB5ID0gcGFydF9hZ2UsIGNvbG9yID0gcmVzcF9nZW5kZXIpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSwgc2l6ZT0xKSsgICMgU2NhdHRlciBwb2ludHMgd2l0aCBzb21lIHRyYW5zcGFyZW5jeQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSkrICMgQWRkaW5nIHJlZ3Jlc3Npb24gbGluZXMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzU2N2I4MSIsICIjYWY1MjY1IiwgIiM3RDdDODQiKSkrCiAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgQmV0d2VlbiBSZXNwb25kZW50J3MgQWdlIGFuZCBQYXJ0bmVyJ3MgQWdlIiwKICAgICAgIHggPSAiUmVzcG9uZGVudCdzIEFnZSIsCiAgICAgICB5ID0gIlBhcnRuZXIncyBBZ2UiLAogICAgICAgY29sb3IgPSAiR2VuZGVyIgogICAgICAgKSsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxMDAsIHkgPSAxMiwgbGFiZWwgPSAiQWdlcyBjb3VwbGVzIGFyZSBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQsCiAgICB3aXRoIHNsaWdodCBkaWZmZXJlbmNlcyBieSBnZW5kZXIiLAogICAgY29sb3IgPSAiIzdEN0M4NCIsIHNpemUgPSAzLjUsIGZvbnRmYWNlPSAiYm9sZC5pdGFsaWMiLCBoanVzdCA9IDEsIGxpbmV3aWR0aD0xKSsKICB0aGVtZV9taW5pbWFsKCkKCmdyYXBoXzQKYGBgCgpiKSAgVXNlIEVkd2FyZCBUdWZ0ZSdzIHByaW5jaXBsZXMgdG8gY3JpdGlxdWUgdGhlIHBsb3QgYWJvdmUuIFdoaWNoIG9mIHRoZSBjaGFuZ2VzIHdvdWxkIGltcHJvdmUgdGhlIHBsb3QgaW4geW91ciBvcGluaW9uPwoKKipBbnN3ZXIqKjogSWYgSSB3ZXJlIFR1ZnRlLCBJIHdvdWxkIHNheSB0aGF0IHRoZSBjb2xvciwgdGhlIGdyaWQgbGluZXMsIGFuZCB0aGUgcmVsYXRpdmVseSBsYXJnZSBkYXRhIHBvaW50cyBhcmUgdW5uZWNlc3NhcnkuIEJhc2VkIG9uIGRhdGEtaW5jLXJhdGlvbiBhbG9uZSwgdGhlIGdyYXBoIGlzIG5vdCBhdCBwYXIgd2l0aCB3aGF0IFR1ZnQgd291bGQgaGF2ZSB2aXNpb25lZCBmb3IgYSBlZmZlY3RpdmUgYW5kIGNvbXBlbGxpbmcgdml6dWFsIGFpZC4gSSB0aGluayB0aGF0IHRoZSBzY2F0dGVyIHBsb3Qgd291bGQgaW1wcm92ZSAoZnJvbSBUdWZ0ZSBzdGFuZGFyZHMpIGZyb20gc21hbGxlciBsbSBsaW5lcywgYW5kIHNtYWxsZXIgZGF0YSBwb2ludHMuIEFkZGl0aW9uYWxseSwgSSB3b3VsZCB1bmJvbGQgdGhlIGFubm90YXRpb24vY2FwdGlvbi4KCiMjIyAzLiBQb2xpdGljcyBhbmQgRGF0aW5nCgphKSAgRXhwbG9yZSBob3cgdGhlIHBvbGl0aWNhbCBhZmZpbGlhdGlvbiBvZiBwYXJ0bmVycyBhZmZlY3RzIGhvdyBjb3VwbGVzIG1lZXQgYW5kIHN0YXkgdG9nZXRoZXIuIENyZWF0ZSB0d28gKDIpIGNoYXJ0cyBpbiB0aGlzIHNlY3Rpb24uIE1ha2Ugc3VyZSB0byB1c2Ugc29tZSB2YXJpYXRpb24gaW4gdGhlIHR5cGUgb2YgdmlzdWFsaXphdGlvbnMuIERpc2N1c3Mgd2hpY2ggdmlzdWFsaXphdGlvbiB5b3UgcmVjb21tZW5kIHRvIHlvdXIgZWRpdG9yIGFuZCB3aHkuCgoqKkNsZWFuaW5nICYgV3JhbmdsaW5nKioKCmBgYHtyfQojIGVuc3VyZSBmYWN0b3IgbGV2ZWxzIGFsaWduIApkZiRyZXNwX3BhcnR5IDwtIGZhY3RvcihkZiRyZXNwX3BhcnR5LCBsZXZlbHMgPSB1bmlvbihsZXZlbHMoZGYkcmVzcF9wYXJ0eSksIGxldmVscyhkZiRwYXJ0X3BhcnR5KSkpCmRmJHBhcnRfcGFydHkgPC0gZmFjdG9yKGRmJHBhcnRfcGFydHksIGxldmVscyA9IHVuaW9uKGxldmVscyhkZiRyZXNwX3BhcnR5KSwgbGV2ZWxzKGRmJHBhcnRfcGFydHkpKSkKCiMgQ3JlYXRlcyAyIG5ldyBjYXRlZ29yaWNhbCB2YXJpYWJsZXM6IHN1bW1hcml6ZXMgcmVzcG9uZGVudHMnIGFuZCBwYXJ0bmVycycgcG9saXRpY2FsIGFmZmlsaWF0aW9ucyBpbnRvIHRocmVlIHBvc3NpYmlsaXRpZXMgKGRlbSwgaW5kLCByZXApCmxpYnJhcnkoZHBseXIpCgpkZiA8LSBkZiAlPiUKICBtdXRhdGUocmVzcF9wYXJ0eV90eXBlID0gY2FzZV93aGVuKAogICAgcmVzcF9wYXJ0eSAlaW4lIGMoIlN0cm9uZyBEZW1vY3JhdCIsICJOb3QgU3Ryb25nIERlbW9jcmF0IiwgIkxlYW5zIERlbW9jcmF0IikgfiAiRGVtIiwKICAgIHJlc3BfcGFydHkgJWluJSBjKCJVbmRlY2lkZWQvSW5kZXBlbmRlbnQvT3RoZXIiKSB+ICJJbmQiLAogICAgcmVzcF9wYXJ0eSAlaW4lIGMoIlN0cm9uZyBSZXB1YmxpY2FuIiwgIk5vdCBTdHJvbmcgUmVwdWJsaWNhbiIsICJMZWFucyBSZXB1YmxpY2FuIikgfiAiUmVwIiAjIEFzc2lnbiBOQSBmb3IgYW55IHVuZXhwZWN0ZWQgdmFsdWVzCiAgKSkKCmRmIDwtIGRmICU+JQogIG11dGF0ZShwYXJ0X3BhcnR5X3R5cGUgPSBjYXNlX3doZW4oCiAgICBwYXJ0X3BhcnR5ICVpbiUgYygiU3Ryb25nIERlbW9jcmF0IiwgIk5vdCBTdHJvbmcgRGVtb2NyYXQiLCAiTGVhbnMgRGVtb2NyYXQiKSB+ICJEZW0iLAogICAgcGFydF9wYXJ0eSAlaW4lIGMoIlVuZGVjaWRlZC9JbmRlcGVuZGVudC9PdGhlciIpIH4gIkluZCIsCiAgICBwYXJ0X3BhcnR5ICVpbiUgYygiU3Ryb25nIFJlcHVibGljYW4iLCAiTm90IFN0cm9uZyBSZXB1YmxpY2FuIiwgIkxlYW5zIFJlcHVibGljYW4iKSB+ICJSZXAiCiAgKSkKCiMgQ3JlYXRlIHRoZSBhbGlnbm1lbnQgdmFyaWFibGU6IHBhcnR5X3BhaXIgCmRmIDwtIGRmICU+JQogIG11dGF0ZShwYXJ0eV9wYWlyID0gcGFzdGUocmVzcF9wYXJ0eV90eXBlLCBwYXJ0X3BhcnR5X3R5cGUsIHNlcCA9ICItIikpCgojIGZpbHRlcmluZyBOQSBwYWlycwpwYXJ0eV9wYWlyX2ZpbHRlcmVkIDwtIGRmICU+JQogIGZpbHRlcihwYXJ0eV9wYWlyICE9ICJEZW0tTkEiICYgcGFydHlfcGFpciAhPSAiSW5kLU5BIiAmIHBhcnR5X3BhaXIgIT0gIlJlcC1OQSIpCgpgYGAKCioqR3JhcGggNTogU3RhY2tlZCBCYXJwbG90IChjb3VudHMpKioKCmBgYHtyfQojZ3JhcGggNTogU3RhY2tlZCBiYXIgY2hhcnQgZm9yIG1lZXRpbmcgdHlwZXMgYnkgcGFydG5lciBhbGlnbm1lbnQgCmdyYXBoXzUgPC0gZ2dwbG90KHBhcnR5X3BhaXJfZmlsdGVyZWQsIGFlcyh4ID0gcGFydHlfcGFpciwgZmlsbCA9IHR5cGVfbWV0KSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gIlN0YWNrIikgKyAgIyBOb3JtYWxpemUgdG8gcHJvcG9ydGlvbnMKICBjb29yZF9mbGlwKCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkrCiAgbGFicygKICAgIHRpdGxlID0gIk1vc3QgUG9wdWxhciBNZWV0aW5nIFR5cGVzIGJ5IFBhcnR5IEFsaWdubWVudCIsCiAgICB4ID0gIlBvbGl0aWNhbCBBbGlnbm1lbnQiLAogICAgeSA9ICJDb3VudHMiLAogICAgZmlsbCA9ICJNZWV0aW5nIFR5cGUiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCgpncmFwaF81CmBgYAoKYGBge3J9CiMgTmV3IERGOiBDb3VudCBvY2N1cnJlbmNlcyBvZiBtZWV0aW5nIHR5cGVzIGZvciBlYWNoIGFsaWdubWVudApwYXJ0eV9wYWlyX2RmIDwtIGRmICU+JQogIGdyb3VwX2J5KHBhcnR5X3BhaXIsIHR5cGVfbWV0KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKQpgYGAKCioqQ2hhcnQgNjogQm94cGxvdCoqCgpgYGB7cn0KIyBDaGFydCA2OiBib3hwbG90IHNob3dpbmcgcGFydHkgYWxpZ25tZW50IG9uIGR1cmF0aW9uIG9mIHJlbGF0aW9uc2hpcHMgIAoKZ3JhcGhfNiA8LSBnZ3Bsb3QocGFydHlfcGFpcl9maWx0ZXJlZCwgYWVzKHggPSBwYXJ0eV9wYWlyLCB5ID0gZHVyYXRpb24sIGZpbGwgPSBwYXJ0eV9wYWlyKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBjb29yZF9mbGlwKCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzU2N2I4MSIsICIjNTY3YjgxIiwgIiM1NjdiODEiLCAiI2QzZDNkMyIsICIjZDNkM2QzIiwgIiNkM2QzZDMiLCAiI2FmNTI2NSIsICIjYWY1MjY1IiwgIiNhZjUyNjUiKSkrCiAgbGFicygKICAgIHRpdGxlID0gIlJlbGF0aW9uc2hpcCBEdXJhdGlvbiBieSBQb2xpdGljYWwgQWxpZ25tZW50IiwKICAgIHggPSBOVUxMLAogICAgeSA9ICJEdXJhdGlvbiBvZiBSZWxhdGlvbnNoaXAgKFllYXJzKSIsCiAgICBmaWxsID0gTlVMTAogICkrIAogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmdyYXBoXzYKCmBgYAoKKipEaXNjdXNzaW9uKio6CgpiKSAgV3JpdGUgYSBzaG9ydCBuYXJyYXRpdmUgKFx+MTUwIHdvcmRzKSBiYXNlZCBvbiB5b3VyIHZpc3VhbGl6YXRpb24sIGludGVncmF0aW5nIGRhdGEgaW5zaWdodHMgd2l0aCBhIGNvbXBlbGxpbmcgc3RvcnkuIFRoaXMgbmFycmF0aXZlIHNob3VsZCBiZSBzdWl0YWJsZSBmb3IgYSBmZWF0dXJlIGFydGljbGUsIGhpZ2hsaWdodGluZyBrZXkgZmluZGluZ3MgYW5kIHRoZWlyIGltcGxpY2F0aW9ucy4KCioqTmFycmF0aXZlKio6IFRoZSB3YXkgY291cGxlcyBtZWV0IGFuZCB0aGUgbG9uZ2V2aXR5IG9mIHRoZWlyIHJlbGF0aW9uc2hpcHMgc2VlbSBjbG9zZWx5IHRpZWQgdG8gcG9saXRpY2FsIGFsaWdubWVudC4gU29jaWFsIHNldHRpbmdzIGRvbWluYXRlIGFzIHRoZSBtb3N0IHBvcHVsYXIgbWVldGluZyB0eXBlIGZvciBwb2xpdGljYWxseSBhbGlnbmVkIGNvdXBsZXMsIHN1Y2ggYXMgIkRlbS1EZW0iIGFuZCAiUmVwLVJlcCwiIHdoaWxlIG1peGVkLWFmZmlsaWF0aW9uIGNvdXBsZXMgbGlrZSAiRGVtLUluZCIgc2hvdyBhIG1vcmUgZGl2ZXJzZSBkaXN0cmlidXRpb24gb2YgbWVldGluZyB0eXBlcywgaW5jbHVkaW5nIG9ubGluZSBwbGF0Zm9ybXMgYW5kIHdvcmstcmVsYXRlZCBhY3Rpdml0aWVzLiBUaGlzIHN1Z2dlc3RzIHRoYXQgc2hhcmVkIHBvbGl0aWNhbCBiZWxpZWZzIG1heSBzdHJlYW1saW5lIHNvY2lhbCBjaXJjbGVzLCBtYWtpbmcgaXQgZWFzaWVyIGZvciBsaWtlLW1pbmRlZCBpbmRpdmlkdWFscyB0byBjb25uZWN0LgoKV2hlbiBpdCBjb21lcyB0byByZWxhdGlvbnNoaXAgZHVyYXRpb24sIGNvdXBsZXMgd2l0aCB0aGUgc2FtZSBwb2xpdGljYWwgYWZmaWxpYXRpb24sIHBhcnRpY3VsYXJseSAiRGVtLURlbSIgYW5kICJSZXAtUmVwLCIgdGVuZCB0byBoYXZlIGxvbmdlci1sYXN0aW5nIHJlbGF0aW9uc2hpcHMgY29tcGFyZWQgdG8gbWl4ZWQtYWZmaWxpYXRpb24gcGFpcnMuIFRoaXMgcGF0dGVybiBoaW50cyBhdCB0aGUgc3RhYmlsaXppbmcgaW5mbHVlbmNlIG9mIHNoYXJlZCB2YWx1ZXMgYW5kIHdvcmxkdmlld3Mgb24gcGFydG5lcnNoaXBzLiBUaGVzZSBmaW5kaW5ncyBoaWdobGlnaHQgaG93IHBvbGl0aWNhbCBpZGVudGl0eSBleHRlbmRzIGJleW9uZCBpZGVvbG9neSwgaW5mbHVlbmNpbmcgYm90aCBob3cgY291cGxlcyBmb3JtIGFuZCBob3cgdGhleSBlbmR1cmUgb3ZlciB0aW1lLgoKIyMjIDQuIFlvdXIgVHVybiB0byBDaG9vc2UKClRoZXJlIGFyZSBsb3RzIG9mIG90aGVyIHZhcmlhYmxlcyB0aGF0IGNvdWxkIG1ha2UgZm9yIGFuIGludGVyZXN0aW5nIHN0b3J5LCBmb3IgZXhhbXBsZSwgZWR1Y2F0aW9uYWwgYmFja2dyb3VuZCBkaWZmZXJlbmNlcywgcmVsYXRpb25zaGlwIHN0YWdlcyAoRmlyc3QgTWV0LCBSb21hbnRpYywgTGl2ZSB0b2dldGhlciAmIE1hcnJpZWQpLCByZWdpb25hbCBwYXR0ZXJucywgcmVsYXRpb25zaGlwIGJyZWFrIHVwcywgc2V4dWFsIGJlaGF2aW9yIGV0Yy4gU2VsZWN0IHNvbWUgdmFyaWFibGVzIG9mIHlvdXIgY2hvaWNlIHRvIHRlbGwgYSBzdG9yeSB0aGF0IGNhcHR1cmVzIGFuIGludGVyZXN0aW5nIGluc2lnaHQgaW50byB0aGUgZGF0YS4KCkNyZWF0ZSBvbmUgKDEpIGNoYXJ0IGluIHRoaXMgc2VjdGlvbiB0byBoaWdobGlnaHQgc29tZSBpbXBvcnRhbnQgcGF0dGVybnMuIEJyaWVmbHkgZGlzY3VzcyB3aGljaCB2aXN1YWxpemF0aW9uIHlvdSByZWNvbW1lbmQgdG8geW91ciBlZGl0b3IsIHdoeSB5b3UgdGhpbmsgdGhlIHZpc3VhbGl6YXRpb24gaXMgdXNlZnVsLCBhbmQgd2hpY2ggcGF0dGVybnMgaXQgc2VydmVzIHRvIGhpZ2hsaWdodC4KCmBgYHtyfQojIHByb2JhYmlsaXR5IG9mIG1hcnJpYWdlIGFjcm9zcyBtZWV0aW5nIHR5cGVzIApkZl9zdGF0dXNfbWFyIDwtIGRmICU+JQogIGZpbHRlcihzaGlwX3N0YXR1cz09ICJtYXJyaWVkIikKCiMgU3VtbWFyaXplIGNvdW50cyBvZiBtZWV0aW5nIHR5cGVzIGZvciBtYXJyaWVkIHJlc3BvbmRlbnRzCnBpZV9tYXJfZGYgPC0gZGZfc3RhdHVzICU+JQogIGdyb3VwX2J5KHR5cGVfbWV0KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKQoKIyBQaWUgY2hhcnQ6IG1hcnJpYWdlIGFjcm9zcyBtZWV0aW5nIHR5cGVzIApncmFwaDcuMSA8LSBnZ3Bsb3QocGllX3NoaXBfZGYsIGFlcyh4ID0gIiIsIHkgPSBjb3VudCwgZmlsbCA9IHR5cGVfbWV0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEsIGNvbG9yID0gIndoaXRlIikrICMgQ3JlYXRlIGJhcnMKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlKSsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0ID0gMCkrICMgVHJhbnNmb3JtIHRvIHBpZSBjaGFydAogICN0aGVtZV92b2lkKCkgKyAjIFJlbW92ZSBheGVzIGFuZCBncmlkcwogIGxhYnModGl0bGUgPSAiQ29tcGFyaW5nIE1lZXRpbmcgVHlwZXMgQmV0d2VlbiBNYXJyaWVkIGFuZCBEaXZvcmNlZC9TZXBhcmF0ZWQgUmVzcG9uZGVudHMiLAogICAgeSA9ICJNYXJyaWVkIiwgeD0icGVyY2VudCIsCiAgKSsKICB0aGVtZV9taW5pbWFsKCkrIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyfQojIHByb2JhYmlsaXR5IG9mIGRpdm9yY2UsIHNlcGFyYXRpb24sIGJyZWFrdXAgYWNyb3NzIG1lZXRpbmcgdHlwZXMgCmRmX3N0YXR1c19kaXZfc2VwIDwtIGRmICU+JQogIGZpbHRlcihlbmRlZF9tYXI9PSAiZGl2b3JjZSIgfCBlbmRlZF9tYXIgPT0gInNlcGFyYXRpb24gd2l0aCBubyBkaXZvcmNlIiB8IGVuZGVkX25vbm1hciA9PSAiV2UgYnJva2UgdXAiKQoKIyBTdW1tYXJpemUgY291bnRzIG9mIG1lZXRpbmcgdHlwZXMgZm9yIG1hcnJpZWQgcmVzcG9uZGVudHMKcGllX25vbm1hcl9kZiA8LSBkZl9zdGF0dXNfZGl2X3NlcCAlPiUKICBncm91cF9ieSh0eXBlX21ldCkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikKCiMgUGllIGNoYXJ0OiBkaXZvcmNlL3NlcGFyYXRpb24gYWNyb3NzIG1lZXRpbmcgdHlwZXMgCmdyYXBoNy4yIDwtZ2dwbG90KHBpZV9ub25tYXJfZGYsIGFlcyh4ID0gIiIsIHkgPSBjb3VudCwgZmlsbCA9IHR5cGVfbWV0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEsIGNvbG9yID0gIndoaXRlIikrIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKwogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArICMgVHJhbnNmb3JtIHRvIHBpZSBjaGFydAogICN0aGVtZV92b2lkKCkgKyAjIFJlbW92ZSBheGVzIGFuZCBncmlkcwogIGxhYnMoCiAgICBmaWxsID0gTlVMTCwgeD0icGVyY2VudCIsCiAgICB5PSJEaXZvcmNlZC9TZXBhcmF0ZWQiCiAgKSsKICB0aGVtZV9taW5pbWFsKCkrIAogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksICAgIyBSZW1vdmUgeC1heGlzIHRleHQKICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIHgtYXhpcyB0aWNrcwogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE0KSwgIyBDZW50ZXIgYW5kIGFkanVzdCB0aXRsZSBzaXplCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICApCgpncmFwaF83X2NvbWIgPC0gZ3JhcGg3LjEgKyBncmFwaDcuMgpncmFwaF83IDwtIGdyYXBoXzdfY29tYiArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKQpncmFwaF83CmBgYAoKKipEaXNjdXNzaW9uKio6IFRoZSBkdWFsIHBpZSBjaGFydCBlZmZlY3RpdmVseSBjb21wYXJlcyBob3cgbWVldGluZyB0eXBlcyBkaWZmZXIgYmV0d2VlbiBtYXJyaWVkIGFuZCBkaXZvcmNlZC9zZXBhcmF0ZWQgcmVzcG9uZGVudHMuIEl0IGhpZ2hsaWdodHMgdGhhdCBzb2NpYWwgc2V0dGluZ3MgYXJlIHByb21pbmVudCBmb3IgYm90aCBncm91cHMsIHdoaWxlIHdvcmstcmVsYXRlZCBhY3Rpdml0aWVzIGFyZSBtb3JlIGNvbW1vbiBhbW9uZyBtYXJyaWVkIGNvdXBsZXMuIFRoZSB1c2Ugb2YgcGVyY2VudGFnZXMgd2l0aGluIGVhY2ggc2xpY2UgKG9ic2VydmluZyB0aGUgdHdvIGludGVyYWN0aXZlIHBsb3RzKSB3b3VsZCBtYWtlIHRoZSBjb21wYXJpc29uIGV2ZW4gY2xlYXJlciwgYWxsb3dpbmcgcmVhZGVycyB0byBlYXNpbHkgZ3Jhc3AgdGhlIHJlbGF0aXZlIGltcG9ydGFuY2Ugb2YgZWFjaCBtZWV0aW5nIHR5cGUuCgojIyBJbnRlcmFjdGl2aXR5CgojIyMgNS4gTWFrZSBUd28gUGxvdHMgSW50ZXJhY3RpdmUKCmEpICBDaG9vc2UgMiBvZiB0aGUgcGxvdHMgeW91IGNyZWF0ZWQgYWJvdmUgYW5kIGFkZCBpbnRlcmFjdGl2aXR5LiBGb3IgYXQgbGVhc3Qgb25lIG9mIHRoZXNlIGludGVyYWN0aXZlIHBsb3RzLCB0aGlzIHNob3VsZCBub3QgYmUgZG9uZSB0aHJvdWdoIHRoZSB1c2Ugb2YgYGdncGxvdGx5YAoKKipJbnRlcmFjdGl2ZSBQbG90IDE6IHBsb3RseSBwaWVjaGFydCB2ZXJzaW9uKioKYGBge3J9CmxpYnJhcnkocGxvdGx5KQoKIyBDcmVhdGUgaW50ZXJhY3RpdmUgcGllIGNoYXJ0CmludGVyYWN0aXZlX3BpZV9tYXIgPC0gcGxvdF9seSgKICBkYXRhID0gcGllX21hcl9kZiwKICBsYWJlbHMgPSB+dHlwZV9tZXQsICAgICMgTWVldGluZyB0eXBlcyBhcyBsYWJlbHMKICB2YWx1ZXMgPSB+Y291bnQsICAgICAgICMgQ291bnRzIGFzIHZhbHVlcwogIHR5cGUgPSAncGllJywgICAgICAgICAgIyBTcGVjaWZ5IHBpZSBjaGFydAogIHRleHRpbmZvID0gJ2xhYmVsK3BlcmNlbnQnLCAjIFNob3cgbGFiZWxzIGFuZCBwZXJjZW50YWdlcwogIGhvdmVyaW5mbyA9ICdsYWJlbCt2YWx1ZStwZXJjZW50JywgIyBIb3ZlciBpbmZvOiBsYWJlbCwgdmFsdWUsIHBlcmNlbnRhZ2UKICBtYXJrZXIgPSBsaXN0KGNvbG9ycyA9IHBhbGV0dGUpICMgQ3VzdG9tIGNvbG9ycwopICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBNZWV0aW5nIFR5cGVzIEFtb25nIE1hcnJpZWQgUmVzcG9uZGVudHMiLAogICAgbGVnZW5kID0gbGlzdChvcmllbnRhdGlvbiA9ICJoIikgIyBIb3Jpem9udGFsIGxlZ2VuZAogICkKaW50ZXJhY3RpdmVfcGllX21hcgoKIyBDcmVhdGUgaW50ZXJhY3RpdmUgcGllIGNoYXJ0CmludGVyYWN0aXZlX3BpZV9kaXZzZXAgPC0gcGxvdF9seSgKICBkYXRhID0gcGllX25vbm1hcl9kZiwKICBsYWJlbHMgPSB+dHlwZV9tZXQsICAgICMgTWVldGluZyB0eXBlcyBhcyBsYWJlbHMKICB2YWx1ZXMgPSB+Y291bnQsICAgICAgICMgQ291bnRzIGFzIHZhbHVlcwogIHR5cGUgPSAncGllJywgICAgICAgICAgIyBTcGVjaWZ5IHBpZSBjaGFydAogIHRleHRpbmZvID0gJ2xhYmVsK3BlcmNlbnQnLCAjIFNob3cgbGFiZWxzIGFuZCBwZXJjZW50YWdlcwogIGhvdmVyaW5mbyA9ICdsYWJlbCt2YWx1ZStwZXJjZW50JywgIyBIb3ZlciBpbmZvOiBsYWJlbCwgdmFsdWUsIHBlcmNlbnRhZ2UKICBtYXJrZXIgPSBsaXN0KGNvbG9ycyA9IHBhbGV0dGUpICMgQ3VzdG9tIGNvbG9ycwopICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBNZWV0aW5nIFR5cGVzIEFtb25nIE1hcnJpZWQgUmVzcG9uZGVudHMiLAogICAgbGVnZW5kID0gbGlzdChvcmllbnRhdGlvbiA9ICJoIikgIyBIb3Jpem9udGFsIGxlZ2VuZAogICkKaW50ZXJhY3RpdmVfcGllX2RpdnNlcApgYGAKCmBgYHtyfQojIEludGVyYWN0aXZlIFBsb3QgMjoKCmdncGxvdGx5KGdyYXBoXzMpCgpgYGAKCioqSW50ZXJhY3RpdmUgUGxvdCAyOioqCgpiKSAgQnJpZWZseSBkZXNjcmliZSB0byB0aGUgZWRpdG9yIHdoeSBpbnRlcmFjdGl2aXR5IGluIHRoZXNlIHZpc3VhbGl6YXRpb25zIGlzIHBhcnRpY3VsYXJseSBoZWxwZnVsIGZvciBhIHJlYWRlciwgcmVmZXJlbmNpbmcgdXNlciBlbmdhZ2VtZW50IHRoZW9yaWVzIG9yIGludGVyYWN0aW9uIGRlc2lnbiBwcmluY2lwbGVzLgoKKipEZXNjcmliZSoqOiBJbnRlcmFjdGl2aXR5IGluIHRoZXNlIHZpc3VhbGl6YXRpb25zIGFsbG93cyByZWFkZXJzIHRvIGV4cGxvcmUgdGhlIGRhdGEgaW4gYSBtb3JlIGVuZ2FnaW5nIGFuZCBpbnR1aXRpdmUgd2F5LiBGb3IgZXhhbXBsZSwgaG92ZXJpbmcgb3ZlciB0aGUgcGllIGNoYXJ0IHNsaWNlcyByZXZlYWxzIGV4YWN0IHBlcmNlbnRhZ2VzIGFuZCBtZWV0aW5nIHR5cGVzLCBtYWtpbmcgaXQgZWFzaWVyIHRvIGNvbXBhcmUgaG93IG1hcnJpZWQgYW5kIGRpdm9yY2VkL3NlcGFyYXRlZCBjb3VwbGVzIG1ldC4gU2ltaWxhcmx5LCB0aGUgbGluZSBncmFwaCBlbmFibGVzIHJlYWRlcnMgdG8gZm9jdXMgb24gc3BlY2lmaWMgdHJlbmRzLCBzdWNoIGFzIHRoZSBzaGFycCByaXNlIG9mIG9ubGluZSBtZWV0aW5nIHBsYXRmb3JtcyBhZnRlciAyMDAwLiBUaGVzZSBmZWF0dXJlcyBtYWtlIHRoZSBkYXRhIG1vcmUgYWNjZXNzaWJsZSBhbmQgZW5jb3VyYWdlIHJlYWRlcnMgdG8gdW5jb3ZlciBpbnNpZ2h0cyBvbiB0aGVpciBvd24uCgojIyMgNi4gRGF0YSBUYWJsZQoKVG8gYWxsb3cgdGhlIHJlYWRlciB0byBleHBsb3JlIHRoZSBzdXJ2ZXkgZGF0YSBieSB0aGVtc2VsdmVzIGEgYml0LCBzZWxlY3QgYSBmZXcgdXNlZnVsIHZhcmlhYmxlcywgcmVuYW1lIHRoZW0gYXBwcm9wcmlhdGVseSBmb3IgdGhlIHRhYmxlIHRvIGJlIHNlbGYtZXhwbGFuYXRvcnksIGFuZCBhZGQgYW4gaW50ZXJhY3RpdmUgZGF0YSB0YWJsZSB0byB0aGUgb3V0cHV0LiBNYWtlIHN1cmUgdGhlIGNvbHVtbnMgYXJlIGNsZWFybHkgbGFiZWxlZC4gU2VsZWN0IHRoZSBhcHByb3ByaWF0ZSBvcHRpb25zIGZvciB0aGUgZGF0YSB0YWJsZSAoZS5nLiBzZWFyY2ggYmFyLCBzb3J0aW5nLCBjb2x1bW4gZmlsdGVycywgaW4tbGluZSB2aXN1YWxpemF0aW9ucyBldGMuIC0tIGFzIGZhciBhcyB0aGUgdG9vbHMgc3VwcGxpZWQgaW4gbGVjdHVyZSBhbGxvdykuCgpgYGB7cn0KIyBJbnRlcmFjdGl2ZSB0YWJsZToKbGlicmFyeShEVCkKCiMgU2VsZWN0IGFuZCByZW5hbWUgcmVsZXZhbnQgY29sdW1ucwppbnRlcmFjdGl2ZV90YWIgPC0gZGYgJT4lCiAgc2VsZWN0KAogICAgdHlwZV9tZXQsIAogICAgc2hpcF9zdGF0dXMsIAogICAgZHVyYXRpb24sCiAgICByZXNwX2dlbmRlciwKICAgIHJlc3BfcGFydHksIAogICAgcGFydF9wYXJ0eQogICkgJT4lCiAgcmVuYW1lKAogICAgYE1lZXRpbmcgVHlwZWAgPSB0eXBlX21ldCwKICAgIGBSZWxhdGlvbnNoaXAgU3RhdHVzYCA9IHNoaXBfc3RhdHVzLAogICAgYExlbmd0aCBvZiBSZWxhdGlvbnNoaXAgKFllYXJzKWAgPSBkdXJhdGlvbiwKICAgIGBSZXNwb25kZW50J3MgR2VuZGVyYCA9IHJlc3BfZ2VuZGVyLAogICAgYFJlc3BvbmRlbnQncyBQb2xpdGljYWwgQWZmaWxpYXRpb25gID0gcmVzcF9wYXJ0eSwKICAgIGBQYXJ0bmVyJ3MgUG9saXRpY2FsIEFmZmlsaWF0aW9uYCA9IHBhcnRfcGFydHkKICApCgojIENyZWF0ZSB0aGUgaW50ZXJhY3RpdmUgZGF0YSB0YWJsZQpkYXRhdGFibGUoCiAgaW50ZXJhY3RpdmVfdGFiLAogIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSBob3ZlciBjb21wYWN0IiwgICMgU3R5bGluZyBvcHRpb25zCiAgZmlsdGVyID0gInRvcCIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGQgY29sdW1uIGZpbHRlcnMgYXQgdGhlIHRvcAogIG9wdGlvbnMgPSBsaXN0KAogICAgcGFnZUxlbmd0aCA9IDEwLCAgICAgICAgICAgICAgICAgICAgICAgICAgICMgTnVtYmVyIG9mIHJvd3MgcGVyIHBhZ2UKICAgIGF1dG9XaWR0aCA9IFRSVUUsICAgICAgICAgICAgICAgICAgICAgICAgICAjIEF1dG9tYXRpY2FsbHkgYWRqdXN0IGNvbHVtbiB3aWR0aHMKICAgIGRvbSA9ICdCZnJ0aXAnLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEFkZCBidXR0b25zIGZvciBleHBvcnQvZG93bmxvYWQKICAgIGJ1dHRvbnMgPSBjKCdjb3B5JywgJ2NzdicsICdleGNlbCcpICAgICAgICAjIEV4cG9ydCBvcHRpb25zCiAgKSwKICBjYXB0aW9uID0gIkV4cGxvcmUgTWVldGluZyBUeXBlcyBhbmQgUmVsYXRpb25zaGlwIERldGFpbHMgb2YgU3VydmV5IFJlc3BvbmRlbnRzIgopCgoKYGBgCgojIyBUZWNobmljYWwgRGV0YWlscwoKVGhlIGRhdGEgY29tZXMgaW4gYSByZWFzb25hYmx5IGNsZWFuIGZpbGUuIEhvd2V2ZXIsIGlmIHlvdSBkbyBmaW5kIGlzc3VlcyB3aXRoIHRoZSBkYXRhLCByZWNvZGUgYW55IHZhbHVlcywgZXRjLiBwbGVhc2UgbWFrZSB0aGlzIGNsZWFyIGluIHRoZSBjb2RlIChhbmQgaWYgc2lnbmlmaWNhbnQgYWRkIGludG8gdGhlIGRlc2NyaXB0aW9uKS4KCklmIG5lZWRlZCBmb3IgeW91ciB2aXN1YWxpemF0aW9uLCB5b3UgY2FuIGFkZCB2aXN1YWwgZHJhcGVyeSBsaWtlIGljb25zLCBpbWFnZXMgZXRjLiBidXQgeW91IGFyZSBjZXJ0YWlubHkgbm90IG9ibGlnYXRlZCB0byBkbyB0aGF0LiBXaGF0IGlzIGltcG9ydGFudCwgaG93ZXZlciwgdG8gKnVzZSBhIGNvbnNpc3RlbnQgc3R5bGUgYWNyb3NzIGFsbCB5b3VyIHZpc3VhbGl6YXRpb25zKi4KClBhcnQgb2YgdGhlIHRhc2sgd2lsbCBiZSB0cmFuc2Zvcm1pbmcgdGhlIGRhdGFzZXQgaW50byBhIHNoYXBlIHRoYXQgYWxsb3dzIHlvdSB0byBwbG90IHdoYXQgeW91IHdhbnQuIEZvciBzb21lIHBsb3RzLCB5b3Ugd2lsbCBuZWNlc3NhcmlseSBuZWVkIHRvIGJlIHNlbGVjdGl2ZSBpbiB3aGF0IHRvIGluY2x1ZGUgYW5kIHdoYXQgdG8gbGVhdmUgb3V0LgoKTWFrZSBzdXJlIHRvIHVzZSAqYXQgbGVhc3QqIHRocmVlIGRpZmZlcmVudCB0eXBlcyBvZiBncmFwaHMsIGUuZy4gbGluZSBncmFwaHMsIHNjYXR0ZXIsIGhpc3RvZ3JhbXMsIGJhciBjaGFydHMsIGRvdCBwbG90cywgaGVhdCBtYXBzLCBldGMuCgojIyBTdWJtaXNzaW9uCgpQbGVhc2UgZm9sbG93IHRoZSBbaW5zdHJ1Y3Rpb25zXSgvRXhlcmNpc2VzL2hvbWV3b3JrX3N1Ym1pc3Npb25faW5zdHJ1Y3Rpb25zLm1kKSB0byBzdWJtaXQgeW91ciBob21ld29yay4gVGhlIGhvbWV3b3JrIGlzIGR1ZSBvbiBGcmlkYXksIEZlYnJ1YXJ5IDIxIGF0IDVwbS4KCiMjIFBsZWFzZSBTdGF5IEhvbmVzdCEKClllcywgdGhpcyB0eXBlIG9mIGRhdGEgaGFzIGJlZW4gYW5hbHl6ZWQgYmVmb3JlLiBJZiB5b3UgZG8gY29tZSBhY3Jvc3Mgc29tZXRoaW5nLCBwbGVhc2Ugbm8gd2hvbGVzYWxlIGNvcHlpbmcgb2Ygb3RoZXIgaWRlYXMuIFdlIGFyZSB0cnlpbmcgdG8gZXZhbHVhdGUgeW91ciBhYmlsaXRpZXMgaW4gdXNpbmcgdGhlIHBhY2thZ2VzIHdlIGRpc2N1c3NlZCB0byBjcmVhdGUgZGF0YSB2aXN1YWxpemF0aW9uIG5vdCB0aGUgYWJpbGl0eSB0byBkbyBpbnRlcm5ldCBzZWFyY2hlcy4gU2ltaWxhcmx5LCBwbGVhc2Ugc3RheSBhd2F5IGZyb20gc29sdXRpb25zIC8gY29kZSBjcmVhdGVkIGJ5IGdlbmVyYXRpdmUgQUkuIEhlcmUgaXMgeW91ciBjaGFuY2UgdG8gbGVhcm4gYW5kIGFwcGx5IHRoZSBjb25jZXB0cyB3ZSBoYXZlIGRpc2N1c3NlZCBpbiBjbGFzcyEKCkFsc28sIHRoaXMgaXMgYW4gaW5kaXZpZHVhbGx5IGFzc2lnbmVkIGV4ZXJjaXNlIC0tIHBsZWFzZSBrZWVwIHlvdXIgc29sdXRpb24gdG8geW91cnNlbGYhCg==